#ifndef EMS_CORE_LOGGER_H
#define EMS_CORE_LOGGER_H

#include <string>
#include <fstream>
#include <mutex>
#include <memory>
#include <sstream>

namespace ems {
namespace core {

enum class LogLevel {
    DEBUG = 0,
    INFO = 1,
    WARN = 2,
    ERROR = 3,
    FATAL = 4
};

// 可选的日志标签（用于控制台彩色输出等）
enum class LogTag {
    NONE = 0,
    MQTT_SEND,
    MQTT_RECV,
};

class Logger {
public:
    static Logger& getInstance();
    
    void initialize(const std::string& logFile, LogLevel level = LogLevel::INFO);
    void log(LogLevel level, const std::string& message, const std::string& file = "", int line = 0);
    // 带标签版本，仅对控制台输出着色，不影响文件输出
    void logTagged(LogLevel level, const std::string& message, const std::string& file, int line, LogTag tag);
    
    void setLevel(LogLevel level) { level_ = level; }
    LogLevel getLevel() const { return level_; }

private:
    Logger() = default;
    ~Logger();
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;
    
    std::string levelToString(LogLevel level) const;
    std::string getCurrentTime() const;
    
    LogLevel level_ = LogLevel::INFO;
    std::ofstream logFile_;
    mutable std::mutex mutex_;
    bool initialized_ = false;
};

}  // namespace core
}  // namespace ems

#define LOG_DEBUG(msg) \
    do { \
        if (ems::core::Logger::getInstance().getLevel() <= ems::core::LogLevel::DEBUG) { \
            std::ostringstream oss; \
            oss << msg; \
            ems::core::Logger::getInstance().log(ems::core::LogLevel::DEBUG, oss.str(), __FILE__, __LINE__); \
        } \
    } while(0)

#define LOG_INFO(msg) \
    do { \
        if (ems::core::Logger::getInstance().getLevel() <= ems::core::LogLevel::INFO) { \
            std::ostringstream oss; \
            oss << msg; \
            ems::core::Logger::getInstance().log(ems::core::LogLevel::INFO, oss.str(), __FILE__, __LINE__); \
        } \
    } while(0)

#define LOG_WARN(msg) \
    do { \
        if (ems::core::Logger::getInstance().getLevel() <= ems::core::LogLevel::WARN) { \
            std::ostringstream oss; \
            oss << msg; \
            ems::core::Logger::getInstance().log(ems::core::LogLevel::WARN, oss.str(), __FILE__, __LINE__); \
        } \
    } while(0)

#define LOG_ERROR(msg) \
    do { \
        if (ems::core::Logger::getInstance().getLevel() <= ems::core::LogLevel::ERROR) { \
            std::ostringstream oss; \
            oss << msg; \
            ems::core::Logger::getInstance().log(ems::core::LogLevel::ERROR, oss.str(), __FILE__, __LINE__); \
        } \
    } while(0)

#define LOG_FATAL(msg) \
    do { \
        std::ostringstream oss; \
        oss << msg; \
        ems::core::Logger::getInstance().log(ems::core::LogLevel::FATAL, oss.str(), __FILE__, __LINE__); \
    } while(0)

// MQTT消息专用的日志宏（控制台彩色输出：send/recv）
#define LOG_MQTT_SEND(msg) \
    do { \
        if (ems::core::Logger::getInstance().getLevel() <= ems::core::LogLevel::INFO) { \
            std::ostringstream oss; \
            oss << msg; \
            ems::core::Logger::getInstance().logTagged(ems::core::LogLevel::INFO, oss.str(), __FILE__, __LINE__, ems::core::LogTag::MQTT_SEND); \
        } \
    } while(0)

#define LOG_MQTT_RECV(msg) \
    do { \
        if (ems::core::Logger::getInstance().getLevel() <= ems::core::LogLevel::INFO) { \
            std::ostringstream oss; \
            oss << msg; \
            ems::core::Logger::getInstance().logTagged(ems::core::LogLevel::INFO, oss.str(), __FILE__, __LINE__, ems::core::LogTag::MQTT_RECV); \
        } \
    } while(0)

#define LOG_MQTT_ERROR(msg) \
    do { \
        if (ems::core::Logger::getInstance().getLevel() <= ems::core::LogLevel::ERROR) { \
            std::ostringstream oss; \
            oss << msg; \
            ems::core::Logger::getInstance().log(ems::core::LogLevel::ERROR, oss.str(), __FILE__, __LINE__); \
        } \
    } while(0)

#define LOG_MQTT_CONN(msg) \
    do { \
        if (ems::core::Logger::getInstance().getLevel() <= ems::core::LogLevel::INFO) { \
            std::ostringstream oss; \
            oss << msg; \
            ems::core::Logger::getInstance().log(ems::core::LogLevel::INFO, oss.str(), __FILE__, __LINE__); \
        } \
    } while(0)

#endif  // EMS_CORE_LOGGER_H
